package cn.dxs.adt.activity;

import android.Manifest;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Message;
import android.os.PowerManager;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.LinearLayout;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.wgl.support.view.PinnedHeaderListView;

import org.litepal.LitePal;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import cn.dxs.adt.R;
import cn.dxs.adt.adapter.AppListPinnedHeaderAdapter;
import cn.dxs.adt.bean.AppInfo;
import cn.dxs.adt.utils.FileUtil;
import cn.dxs.adt.utils.SigUtil;
import cn.dxs.adt.utils.Util;

public class AppListActivity extends BaseActivity implements ExpandableListView.OnChildClickListener {

    private static final String TAG = AppListActivity.class.getSimpleName();
    private static final int HANDLER_DATA = 1000;
    private static final int HANDLER_DATA_UPDATE = 1001;
    private static final int REQUEST_CODE = 1024;

    @BindView(R.id.toolbar)
    Toolbar toolbar;
    private boolean bStop;// 停止遍历

    private LinearLayout mLl_loading;
    private EditText mEt_search;
    private PinnedHeaderListView mLv_applist;
    private AppListPinnedHeaderAdapter mAdp_appListPinnedHeader;

    private List<String> mParent = Arrays.asList(new String[]{"未加固(cocos2djs)", "未加固", "360加固(cocos2djs)", "腾讯御安全(cocos2djs)", "360加固", "腾讯御安全"});
    private Map<String, ArrayList<AppInfo>> mDatas = new HashMap<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_app_list);
        initToolBar(toolbar, true, getTitle());
        init();
    }

    private void init() {
        initView();
        initData();
    }

    private void initView() {
        mLl_loading = (LinearLayout) findViewById(R.id.ll_myscript_loading);
        mEt_search = (EditText) findViewById(R.id.et_search);
        mLv_applist = (PinnedHeaderListView) findViewById(R.id.lv_app_list);
    }

    private void initData() {
        mLv_applist.setOnChildClickListener(this);
        checkNeedPermissions();
        for (int i = 0; i < mParent.size(); i++) {
            mDatas.put(mParent.get(i), new ArrayList<>());
        }
        fillData();
    }

    private void checkNeedPermissions() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return;
        }

        requestPermission();

        // 读写手机存储权限
        if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
            Toast.makeText(this, "请授予读写手机存储权限，并设置允许后台运行", Toast.LENGTH_SHORT).show();
        }

        // 请求悬浮窗权限
        if (!Settings.canDrawOverlays(this)) {
            Intent intent_dol = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
            intent_dol.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent_dol, PackageManager.MATCH_ALL);
            if (resolveInfo != null) {
                startActivity(intent_dol);
            } else {
                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
            }
            Toast.makeText(this, "请授予应用悬浮窗权限，并设置允许后台运行", Toast.LENGTH_SHORT).show();
        }

        // 省电优化白名单
//        if (!((PowerManager) getSystemService(POWER_SERVICE)).isIgnoringBatteryOptimizations(getPackageName())) {
//            Intent intent_ibo = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, Uri.parse("package:" + getPackageName()));
//            intent_ibo.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//            ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent_ibo, PackageManager.MATCH_ALL);
//            if (resolveInfo != null) {
//                startActivity(intent_ibo);
//            }
//            Toast.makeText(this, "请授予应用省电白名单权限", Toast.LENGTH_SHORT).show();
//        }
    }

    /**
     * 刷新界面
     */
    private void fillData() {
        mLl_loading.setVisibility(View.VISIBLE);
        new Thread() {
            public void run() {
                // 所有的应用程序信息

                long startTime = System.currentTimeMillis();
                // 获取已经安装的所有应用, PackageInfo　系统类，包含应用信息
                List<PackageInfo> packages = getPackageManager().getInstalledPackages(0);
                for (int i = 0; i < packages.size(); i++) {
                    if (bStop) {
                        return;
                    }
                    PackageInfo packageInfo = packages.get(i);
//                    if (!"com.yz.mhzy".equals(packageInfo.packageName)) {
//                        continue;
//                    }
                    if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                        continue;
                    }

                    List<AppInfo> appInfoList = LitePal.where("packagename = ? and versionname = ? and versioncode = ?", packageInfo.packageName, packageInfo.versionName, String.valueOf(packageInfo.versionCode)).order("packagename desc").find(AppInfo.class);
                    AppInfo appInfo;
                    if (appInfoList != null && !appInfoList.isEmpty()) {
                        appInfo = appInfoList.get(0);
                        appInfo.appIcon = packageInfo.applicationInfo.loadIcon(getPackageManager());//获取应用图标
                    } else {
                        // AppInfo 自定义类，包含应用信息
                        appInfo = new AppInfo();
                        appInfo.appIcon = packageInfo.applicationInfo.loadIcon(getPackageManager());//获取应用图标
                        appInfo.appName = packageInfo.applicationInfo.loadLabel(getPackageManager()).toString();//获取应用名称
                        appInfo.packageName = packageInfo.packageName; //获取应用包名，可用于卸载和启动应用
                        appInfo.versionName = packageInfo.versionName;//获取应用版本名
                        appInfo.versionCode = packageInfo.versionCode;//获取应用版本号
                        appInfo.stub = Util.getStub(packageInfo.applicationInfo.className);

                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                            appInfo.minSdkVersion = packageInfo.applicationInfo.minSdkVersion + "(" + ")";
                        }
                        appInfo.targetSdkVersion = packageInfo.applicationInfo.targetSdkVersion + "(" + ")";
                        appInfo.UID = packageInfo.applicationInfo.uid;
                        appInfo.isSystem = (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
                        appInfo.apkPath = packageInfo.applicationInfo.sourceDir;
                        appInfo.apkSize = Util.getFileSize(appInfo.apkPath);
                        Signature signature = SigUtil.getSignature(packageInfo.packageName);
                        appInfo.sig = SigUtil.getSig(signature);
                        appInfo.MD5 = SigUtil.getMD5(signature);
                        appInfo.SHA1 = SigUtil.getSHA1(signature);
                        appInfo.SHA256 = SigUtil.getSHA256(signature);
                        SigUtil.getSignaturesFromApk(appInfo);
//                    public String signatureOwner;//签名所有者
//                    public String signaturePublisher;//签名发布者
//                    public String signatureSerialNumber;//签名序列号
//                    public String signatureAlgorithmName;//签名算法名称
//                    public String signatureVersion;//签名版本
//                    public String signatureExpiryDateStart;//有效期开始日期
//                    public String signatureExpiryDateEnd;//有效期截止日期
                        appInfo.nativePath = packageInfo.applicationInfo.nativeLibraryDir;
                        appInfo.appDataDirectory = packageInfo.applicationInfo.dataDir;

                        appInfo.mainEntryClassName = Util.getMainEntryClassName(getPackageManager(), appInfo.packageName);
                        appInfo.applicationClassName = packageInfo.applicationInfo.className;
                        appInfo.mainCPUABI = appInfo.nativePath.substring(appInfo.nativePath.lastIndexOf("/") + 1);

                        appInfo.firstInstallTime = Util.getLastModifiedTime(packageInfo.firstInstallTime);
                        appInfo.lastUpdateTime = Util.getLastModifiedTime(packageInfo.lastUpdateTime);
                        appInfo.lfirstInstallTime = packageInfo.firstInstallTime;
                        appInfo.llastUpdateTime = packageInfo.lastUpdateTime;

//                    appInfo.requestedPermissionInfo = Util.getRequestedPermissionInfo(getPackageManager(), appInfo.apkPath);
//                    appInfo.activityInfo = Util.getActivityInfo(getPackageManager(), appInfo.apkPath);
//                    appInfo.serviceInfo = Util.getServiceInfo(getPackageManager(), appInfo.apkPath);
//                    appInfo.receiverInfo = Util.getReceiverInfo(getPackageManager(), appInfo.apkPath);
//                    appInfo.providerInfo = Util.getProviderInfo(getPackageManager(), appInfo.apkPath);

                        appInfo.save();
                    }

                    if (appInfo.isCocos2djs) {
                        if (mDatas.containsKey(appInfo.stub + "(cocos2djs)")) {
                            mDatas.get(appInfo.stub + "(cocos2djs)").add(appInfo);
                        } else {
                            ArrayList<AppInfo> list = new ArrayList<>();
                            list.add(appInfo);
                            mDatas.put(appInfo.stub + "(cocos2djs)", list);
                        }
                    } else {
                        if (mDatas.containsKey(appInfo.stub)) {
                            mDatas.get(appInfo.stub).add(appInfo);
                        } else {
                            ArrayList<AppInfo> list = new ArrayList<>();
                            list.add(appInfo);
                            mDatas.put(appInfo.stub, list);
                        }
                    }

                    sendMsg(HANDLER_DATA_UPDATE, (i + 1) + "-" + appInfo.appName + "-" + Util.getCountdown(startTime));
                }

                Iterator<Map.Entry<String, ArrayList<AppInfo>>> iterator = mDatas.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, ArrayList<AppInfo>> entry = iterator.next();
                    Collections.sort(entry.getValue());
                }

                mHandler.sendEmptyMessage(HANDLER_DATA);
            }
        }.start();
    }

    @Override
    protected void parserMessage(Message msg) {
        super.parserMessage(msg);
        switch (msg.what) {
            case HANDLER_DATA:
                setAdpData();
                break;
            case HANDLER_DATA_UPDATE:
                mEt_search.setHint("搜索应用(" + msg.obj + ")");
                break;
        }
    }

    /**
     * 給适配器设置数据
     */
    private void setAdpData() {
        mLl_loading.setVisibility(View.INVISIBLE);
        if (mAdp_appListPinnedHeader == null) {
            mAdp_appListPinnedHeader = new AppListPinnedHeaderAdapter(mLv_applist, mParent, mDatas);
            mLv_applist.setAdapter(mAdp_appListPinnedHeader);
            mLv_applist.setHeaderView(getLayoutInflater().inflate(R.layout.parent_layout, mLv_applist, false));
        } else {
            mAdp_appListPinnedHeader.notifyDataSetChanged();
        }
    }

    @Override
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            String key = mParent.get(groupPosition);
            AppInfo appInfo = mDatas.get(key).get(childPosition);
            StringBuilder sb = new StringBuilder();
            sb.append(Environment.getExternalStorageDirectory().getAbsolutePath()).append(File.separator);
            sb.append(getPackageName()).append(File.separator);
            sb.append(key).append(File.separator);
            sb.append(appInfo.appName).append("_");
            sb.append(appInfo.packageName).append("_");
            sb.append(appInfo.versionName).append("_");
            sb.append(appInfo.versionCode).append(".apk");
            new Thread() {
                @Override
                public void run() {
                    if (FileUtil.copyFile(appInfo.apkPath, sb.toString())) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                showToast("备份成功: " + appInfo.appName);
                            }
                        });
                    }
                }
            }.start();
        } else {
            showToast("SD卡不存在");
        }
        return true;
    }

    private void requestPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // 先判断有没有权限
            if (Environment.isExternalStorageManager()) {
                writeFile();
            } else {
                Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                intent.setData(Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, REQUEST_CODE);
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 先判断有没有权限
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                writeFile();
            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
            }
        } else {
            writeFile();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                writeFile();
            } else {
                showToast("存储权限获取失败");
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (Environment.isExternalStorageManager()) {
                writeFile();
            } else {
                showToast("存储权限获取失败");
            }
        }
    }

    /**
     * 模拟文件写入
     */
    private void writeFile() {
        showToast("存储权限已获取，请愉快的玩耍吧！");
    }

    /**
     * 调用OptionMenu，在这里完成菜单初始化
     *
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_app_list, menu);
        return super.onCreateOptionsMenu(menu);
    }

    /**
     * 菜单项被选中时触发，这里完成事件处理
     *
     * @param item
     * @return
     */
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.sort_app_name:
                appNameSort();
                break;
            case R.id.sort_last_update_time:
                lastUpdateTimeSort();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    private void appNameSort() {
        if (mDatas == null || mDatas.isEmpty() || mLl_loading.getVisibility() == View.VISIBLE) {
            return;
        }

        new Thread() {
            @Override
            public void run() {
                Iterator<Map.Entry<String, ArrayList<AppInfo>>> iterator = mDatas.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, ArrayList<AppInfo>> entry = iterator.next();
                    Collections.sort(entry.getValue());
                }
                mHandler.sendEmptyMessage(HANDLER_DATA);
            }
        }.start();
    }

    private void lastUpdateTimeSort() {
        if (mDatas == null || mDatas.isEmpty() || mLl_loading.getVisibility() == View.VISIBLE) {
            return;
        }

        new Thread() {
            @Override
            public void run() {
                Iterator<Map.Entry<String, ArrayList<AppInfo>>> iterator = mDatas.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, ArrayList<AppInfo>> entry = iterator.next();
                    Collections.sort(entry.getValue(), new Comparator<AppInfo>() {
                        @Override
                        public int compare(AppInfo o1, AppInfo o2) {
                            if (o1.llastUpdateTime > o2.llastUpdateTime) {
                                return -1;
                            }
                            return 1;
                        }
                    });
                }
                mHandler.sendEmptyMessage(HANDLER_DATA);
            }
        }.start();
    }

    /**
     * 菜单关闭会调用该方法
     *
     * @param menu
     */
    @Override
    public void onOptionsMenuClosed(Menu menu) {
        super.onOptionsMenuClosed(menu);
    }

    /**
     * 选项菜单显示前会调用该方法， 可在这里进行菜单的调整(动态加载菜单列表)
     *
     * @param menu
     * @return
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        return super.onPrepareOptionsMenu(menu);
    }

    /**
     * 选项菜单打开以后会调用这个方法
     *
     * @param featureId
     * @param menu
     * @return
     */
    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        return super.onMenuOpened(featureId, menu);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        bStop = true;
    }
}